//
//  Shaker.cpp
//  client
//
//  Created by Duan Hongbo on 13-11-1.
//
//

#include "Shaker.h"
#include "cocos2d.h"

// not really useful, but I like clean default constructors
Shaker::Shaker() : _strength_x(0), _strength_y(0), _initial_x(0), _initial_y(0)
{
}

Shaker* Shaker::create( float d, float strength )
{
    // call other construction method with twice the same strength
	return create(d, strength, strength, 0, 1.0, 0, 1.0, 0, 1.0);
}

Shaker* Shaker::create(float duration, float strength_x, float strength_y)
{
    Shaker *p_action = new Shaker();
    p_action->initWithDuration(duration, strength_x, strength_y, 0, 1.0, 0, 1.0, 0, 1.0);
    p_action->autorelease();
    
    return p_action;
}

Shaker* Shaker::create(float d, float strength_x, float strength_y, int interval, float intervalFactor, float damping_x, float damping_x_Factor, float damping_y, float damping_y_Factor)
{
    Shaker *p_action = new Shaker();
	p_action->initWithDuration(d, strength_x, strength_y, interval, intervalFactor, damping_x, damping_x_Factor, damping_y, damping_y_Factor);
    p_action->autorelease();
    
    return p_action;
}

bool Shaker::initWithDuration(float duration, float strength_x, float strength_y, int interval, float intervalFactor, float damping_x, float damping_x_Factor, float damping_y, float damping_y_Factor)
{
    if (CCActionInterval::initWithDuration(duration))
    {
        _strength_x = strength_x;
        _strength_y = strength_y;
        _interval = interval;
		_intervalFactor = intervalFactor;
		_damping_x = damping_x;
		_damping_x_Factor = damping_x_Factor;
		_damping_y = damping_y;
		_damping_y_Factor = damping_y_Factor;
        _time = 0.0f;
		for (ShakerQuadrant i = SQ_First; i < SQ_Max; i = (ShakerQuadrant)(i + 1))
		{
			quadrantRandList.push_back(i);
		}

		_quadrant_index = SQ_First;
        return true;
    }
    
    return false;
}


// Helper function. I included it here so that you can compile the whole file
// it returns a random value between min and max included
float fgRangeRand( float min, float max )
{
    float rnd = ((float)rand()/(float)RAND_MAX);
    return rnd*(max-min)+min;
}

void Shaker::update(float time)
{
    _time+= (time*1000);
    if(_time>=_interval)
    {
		float old_strength_x = _strength_x;
		float old_strength_y = _strength_y;
        
        _strength_x -= _damping_x;
		if (_strength_x < 0)
		{
			_strength_x = 0;
		}
        _strength_y -= _damping_y;
		if (_strength_y < 0)
		{
			_strength_y = 0;
		}
        
        _time = 0.0f;

		float randx = fgRangeRand(_strength_x, old_strength_y);
		float randy = fgRangeRand(_strength_y, old_strength_y);

		int randIndex = rand() % quadrantRandList.size();
		_quadrant_index = quadrantRandList.at(randIndex);
		quadrantRandList.erase(quadrantRandList.begin() + (randIndex));
		switch (_quadrant_index)
		{
		case SQ_First:
			
			break;
		case SQ_Second:
			randy = -randy;
			break;
		case SQ_Third:
			randx = -randx;
			randy = -randy;
			break;
		case SQ_Fourth:
			randx = -randx;
			break;
		default:
			break;
		}
		// move the target to a shaked position
		_target->setPosition(Vec2(randx, randy));
		quadrantRecordList.push_back(_quadrant_index);

		if (quadrantRecordList.size() > 2)
		{
			quadrantRandList.push_back(quadrantRecordList.front());
			quadrantRecordList.pop_front();
		}

		_interval = _interval*_intervalFactor;

		_damping_x = _damping_x*_damping_x_Factor;
		_damping_y = _damping_y*_damping_y_Factor;
    }
}

void Shaker::startWithTarget(Node *pTarget)
{
    CCActionInterval::startWithTarget( pTarget );
    
    // save the initial position
    _initial_x = pTarget->getPosition().x;
    _initial_y = pTarget->getPosition().y;
}

void Shaker::stop(void)
{
    // Action is done, reset clip position
    _target->setPosition( Vec2( _initial_x, _initial_y ) );
    
    CCActionInterval::stop();
}